﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using IFDB.Models.Contexts;
using IFDB.Models.Tables;
using IFDB.ResourceLibrary;
using IFDB.ViewModels.Foundation;
using IFDB.ViewModels.PartialViewModels.Interfaces;

namespace IFDB.ViewModels.PartialViewModels
{
    public class PersonAppearancesViewModel : BaseViewModel, IPersonAppearancesViewModel
    {
        public PersonAppearancesViewModel(Guid personId, Guid? seasonId)
        {
            using (IFDBContext db = new IFDBContext())
            {
                this.Person = db.Persons.Single(p => p.PersonId == personId);
                this.Season = seasonId != null ? db.Seasons.Single(s => s.SeasonId == seasonId) : db.Seasons.Single(s => s.Country == Country.England && s.StartDate <= DateTime.Now && s.EndDate >= DateTime.Now);
            }
            
            
            ProcessPersonAppearances();
        }

        public Person Person { get; set; }
        public Season Season { get; set; }

        public IList<PersonSeasonItemViewModel> PersonCareerList { get; set; }
        public IList<AppearanceEvent> PersonSeasonEventList { get; set; }

        private void ProcessPersonAppearances()
        {
            PersonCareerList = new List<PersonSeasonItemViewModel>();
            PersonSeasonEventList = new List<AppearanceEvent>();

            using (IFDBContext db = new IFDBContext())
            {
                var query = (from a in db.AppearanceEvents
                            .Include(a => a.Match)
                            .Include(a => a.Match.Competition)
                            .Include(a => a.Match.Venue)
                            .Include(a => a.Match.Team1)
                            .Include(a => a.Match.Team2)
                            where a.PersonId == Person.PersonId
                            && a.Match.MatchStatus == MatchStatus.FullMatch || a.Match.MatchStatus == MatchStatus.ScoreOnly
                            orderby a.Match.MatchDate descending, a.Minute, a.Plus
                            select a).ToList();

                Guid previousSeasonId = Guid.Empty;

                foreach (var group in query.GroupBy(e => e.MatchId))
                {
                    Match match = group.Take(1).Single().Match;

                    DateTime matchDate = match.MatchDate;
                    Season season = db.Seasons.Single(s => s.StartDate <= matchDate && s.EndDate >= matchDate);

                    short started = 0;
                    short usedSubstitute = 0;
                    short goals = 0;
                    short ownGoals = 0;
                    short yellowCards = 0;
                    short redCards = 0;

                    foreach (var appearanceEvent in group)
                    {
                        switch (appearanceEvent.MatchEventType)
                        {
                            case MatchEventType.Started:
                                started++;
                                break;

                            case MatchEventType.Substitution:
                                usedSubstitute++;
                                break;

                            case MatchEventType.Goal:
                                goals++;
                                break;

                            case MatchEventType.OwnGoal:
                                ownGoals++;
                                break;

                            case MatchEventType.YellowCard:
                                yellowCards++;
                                break;

                            case MatchEventType.RedCard:
                                redCards++;
                                break;
                        }

                        if (season.SeasonId == Season.SeasonId)
                            PersonSeasonEventList.Add(appearanceEvent);
                    }

                    if (season.SeasonId != previousSeasonId)
                    {
                        PersonCareerList.Add(new PersonSeasonItemViewModel()
                        {
                            Team = group.First().Team,
                            Season = season,
                            Started = started,
                            UsedSubstitute = usedSubstitute,
                            Goals = goals,
                            OwnGoals = ownGoals,
                            YellowCards = yellowCards,
                            RedCards = redCards
                        });

                        previousSeasonId = season.SeasonId;
                    }
                    else
                    {
                        PersonSeasonItemViewModel personSeasonItemViewModel = PersonCareerList.Single(p => p.Team == group.First().Team && p.Season == season);
                        personSeasonItemViewModel.Started += started;
                        personSeasonItemViewModel.UsedSubstitute += usedSubstitute;
                        personSeasonItemViewModel.Goals += goals;
                        personSeasonItemViewModel.OwnGoals += ownGoals;
                        personSeasonItemViewModel.YellowCards += yellowCards;
                        personSeasonItemViewModel.RedCards += redCards;
                    }
                }
            }
        }
    }
}
